#include <iostream>
#include <map>
#include <string>
#include <boost/variant.hpp>
#include <boost/function.hpp>
#include <boost/bind.hpp>

using namespace std;

class AVisitor
    : public boost::static_visitor<>
{
public:
	AVisitor(string p) 
		: boost::static_visitor<>(), 
		  _p(p)
	{

	}
    template <typename R>
    void operator()(boost::function<R> f) const
    {
        f();
    }

    template <typename R, typename P1>
    void operator()(boost::function<R (P1)> f) const
    {
        f(1);
    }
	
    template <typename R, typename P1, typename P2>
    void operator()(boost::function<R (P1, P2)> f) const
    {
		cout << "template type: " << typeid(R).name() << " " << typeid(P1).name() << " " << typeid(P2).name() << endl;
		cout << "parameter is: " << _p << endl;
        f(1, 2);
    }

private:
	string _p;

};


class A {
public:
	A() {
		m_func_pool["func1"] = boost::function<bool (int)>(boost::bind<bool>(&A::func1, this, _1));
		m_func_pool["func2"] = boost::function<bool (int, int)>(boost::bind<bool>(&A::func2, this, _1, _2));
		m_func_pool["func3"] = boost::function<bool (int, int)>(boost::bind<bool>(&A::func3, this, _1, _2));
		m_func_pool["func4"] = boost::function<bool (int, float)>(boost::bind<bool>(&A::func4, this, _1, _2));
		m_func_pool["func5"] = boost::function<bool (float, float)>(boost::bind<bool>(&A::func5, this, _1, _2));

	}
	bool func1(int arg1) {
		cout << "func1 called with " << arg1 << endl;
		return true;
	}

	bool func2(int arg1, int arg2)  {
		cout << "func2 called with " << arg1 << " and " << arg2 << endl;
		return true;
	}

	bool func3(int arg1, int arg2) {
		cout << "func3 called with " << arg1 << " and " << arg2 << endl;
		return true;
	}

	bool func4(int arg1, float arg2) {
		cout << "func3 called with " << arg1 << " and " << arg2 << endl;
		return true;
	}
	
	bool func5(float arg1, float arg2) {
		cout << "func3 called with " << arg1 << " and " << arg2 << endl;
		return true;
	}

	bool dispatch(const string& p ) {
		if(m_func_pool.find(p) != m_func_pool.end()) {
			boost::apply_visitor(AVisitor(p), m_func_pool[p]);
		} else {
			cout << p << "is not supported" << endl;
		}

		return true;
	}

private:
	typedef boost::variant<boost::function<bool (int)>, 
							boost::function<bool (int, int)>, 
							boost::function<bool (int, float)>,
							boost::function<bool (float, float)>
							> mfunc_t;
	typedef map<string, mfunc_t> func_pool_t;

	func_pool_t m_func_pool;

};


int main() {
	A a = A();
	a.dispatch("func1");
	a.dispatch("func2");
	a.dispatch("func3");
	a.dispatch("func4");
	a.dispatch("func5");
	a.dispatch("func6");
	int b;
	cin >> b;
	return 0;

}






